#ifndef PERIODICVND_HPP_
#define PERIODICVND_HPP_

#include "../../OptFrame/Heuristic.hpp"
#include "../../OptFrame/NSEnum.hpp"
#include "../../OptFrame/Evaluator.hpp"
#include <algorithm>

class Periodic_VND: public Heuristic<RepPRVP, MemPRVP>
{
public:
	using Heuristic<RepPRVP, MemPRVP>::exec; // prevents name hiding

	Periodic_VND(Evaluator<RepPRVP, MemPRVP>& _ev, vector<Heuristic<RepPRV, MemPRVP>*> _neighbors, RandGen& _rg, PRVPProblemInstance& _pPRVP) :
		ev(_ev), neighbors(_neighbors), rg(_rg), pPRVP(_pPRVP)
	{
	}
	;

	virtual ~Periodic_VND()
	{
	}

	virtual void exec(Solution<RepPRVP>& s, double timelimit, double target_f)
	{
		Evaluation<MemPRVP>& e = ev.evaluate(s.getR());

		exec(s, e, timelimit, target_f);

		delete &e;
	}
	;

	virtual void exec(Solution<RepPRVP>& s, Evaluation<MemPRVP>& e, double timelimit, double target_f)
	{
		//adicionando avaliação para o PRV
		PRVEvaluator evPRV(pPRVP);

		PRVPEvaluator ev(pPRVP);

		//declarando o RVND
		//VariableNeighborhoodDescent<RepPRV, MemPRVP> rvnd(evPRV, neighbors);
		RVND<RepPRV, MemPRVP> rvnd(evPRV, neighbors, rg);

		vector<bool>& status = e.getM().getStatus();

		for (int p = 0; p < s.getR().size(); ++p)
		{
			e.getM().setCurrentPeriod(p);
			if (status.at(p))
			{
				//cout<<"########### periodo: "<<p<<endl;
				//separando somente o periodo atual
				TestSolution<RepPRV>* sol = new TestSolution<RepPRV> (s.getR().at(p));
				//executando o RVND
				EvaluationPRV& ePRV = evPRV.evaluate(sol->getR());
				double iniEv = ePRV.getObjFunction();
				double iniInf = ePRV.getInfMeasure();
				rvnd.exec(*sol, ePRV, timelimit, target_f);
				//atualizando a solução
				double endEv = ePRV.getObjFunction();
				double endInf = ePRV.getInfMeasure();

				s.getR().at(p) = sol->getR();
				e.setObjFunction(e.getObjFunction() + (endEv - iniEv));
				e.setInfMeasure(e.getInfMeasure() + (endInf - iniInf));
				delete sol;
				delete &ePRV;

				//setando que foi feita a busca local nesse periodo
				status.at(p) = false;
			}
		}

		//		e = ev.evaluate(s.getR());
	}
	;

private:
	vector<Heuristic<RepPRV, MemPRVP>*> neighbors;
	Evaluator<RepPRVP, MemPRVP>& ev;
	RandGen& rg;
	PRVPProblemInstance& pPRVP;
};

#endif /*PERIODICVND_HPP_*/
